/*
 * Copyright (c) gitee.com/jiandong001.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import { Responder } from './Responder';
import { MessageCallback } from './ReconnectingWebSocket';
import { ReconnectingWebSocket } from './ReconnectingWebSocket';
import { ConnectionCallback } from './ReconnectingWebSocket';
import { PackagerConnectionSettings } from './PackagerConnectionSettings';
import { RequestHandler } from './RequestHandler';

import Url from '@ohos.url'
import hilog from '@ohos.hilog';
import HashMap from '@ohos.util.HashMap';

class ResponderImpl implements Responder {
  private static readonly TAG = "React ResponderImpl";
  private mId: Object;
  private mClient: JSPackagerClient;

  public constructor(id: Object, client: JSPackagerClient) {
    this.mId = id;
    this.mClient = client
  }

  public respond(result: Object): void {
    try {
//      let message = new JSONObject();
//      message.put("version", JSPackagerClient.PROTOCOL_VERSION);
//      message.put("id", this.mId);
//      message.put("result", result);
      //  mWebSocket.sendMessage(message.toString());

      let message = {
        version: JSPackagerClient.PROTOCOL_VERSION,
        id: this.mId,
        result: result
      }
      this.mClient.getWebSocket().sendMessage(JSON.stringify(message));
    } catch (e: any) {
      hilog.error(0x0000, ResponderImpl.TAG, '%{public}s', 'Responding failed' + (e as Error).message);
    }
  }

  public error(error: Object): void {
    try {
//      let message: JSONObject = new JSONObject();
//      message.put("version", JSPackagerClient.PROTOCOL_VERSION);
//      message.put("id", this.mId);
//      message.put("error", error);
      //mWebSocket.sendMessage(message.toString());

      let message = {
        version: JSPackagerClient.PROTOCOL_VERSION,
        id: this.mId,
        error: error
      }
      this.mClient.getWebSocket().sendMessage(JSON.stringify(message));
    } catch (e) {
      hilog.error(0x0000, ResponderImpl.TAG, '%{public}s', 'Responding with error failed' + (e as Error).message);
    }
  }
}

export class JSPackagerClient implements MessageCallback {
  private static readonly TAG = "React JSPackagerClient";
  public static readonly PROTOCOL_VERSION = 2;
  private mWebSocket: ReconnectingWebSocket;
  private mRequestHandlers: HashMap<String, RequestHandler>;

  public constructor(
    clientId: string,
    settings: PackagerConnectionSettings,
    requestHandlers: HashMap<string, RequestHandler>,
    connectionCallback?: ConnectionCallback) {
    // super();

//    let builder: Uri.Builder = new Uri.Builder();
//    builder
//      .scheme("ws")
//      .encodedAuthority(settings.getDebugServerHost())
//      .appendPath("message")
////      .appendQueryParameter("device", AndroidInfoHelpers.getFriendlyDeviceName())
//      .appendQueryParameter("app", settings.getPackageName())
//      .appendQueryParameter("clientid", clientId);
//    let url: string = builder.build().toString();

    let  url = `ws://localhost:8081/message?device=VOG-AL00%20-%2010%20-%20API%2029&app=com.helloworld&clientid=BridgeDevSupportManager`
    this.mWebSocket = new ReconnectingWebSocket(url, this, connectionCallback);
    this.mRequestHandlers = requestHandlers;
    hilog.info(0x0000, JSPackagerClient.TAG, "constructor %{public}s", url);

  }

  public init() {
    this.mWebSocket.connect();
  }

  public close() {
    this.mWebSocket.closeQuietly();
  }

  public getWebSocket(): ReconnectingWebSocket {
    return this.mWebSocket
  }

  public onMessage(text: string): void {
    try {
//      let message = new JSONObject(text);
//
//      let version: number = message.optInt("version");
//      let method: string = message.optString("method");
//      let id: Object = message.opt("id");
//      let params: Object = message.opt("params");

      let message = JSON.parse(text)
      let version: number = message.version;
      let method: string = message.method;
      let id: Object = message.id;
      let params: Object = message.params;


      if (version != JSPackagerClient.PROTOCOL_VERSION) {
        hilog.error(0x0000, JSPackagerClient.TAG, '%{public}s', 'Message with incompatible or missing version of protocol received' + version);
        return;
      }

      if (method == null || method == '') {
        this.abortOnMessage(id, "No method provided");
        return;
      }

      let handler: RequestHandler = this.mRequestHandlers.get(method);
      if (handler == null) {
        this.abortOnMessage(id, "No request handler for method: " + method);
        return;
      }

      if (id == null) {
        handler.onNotification(params);
      } else {
        handler.onRequest(params, new ResponderImpl(id, this));
      }
    } catch (e: any) {
      hilog.error(0x0000, JSPackagerClient.TAG, '%{public}s', 'Handling the message failed' + (e as Error).message);
    }
  }

  //@Override
//  public onMessage(bytes: ByteString): void {
//    hilog.warn(0x0000, JSPackagerClient.TAG, '%{public}s', 'Websocket received message with payload of unexpected type binary');
//  }

  private abortOnMessage(id: Object, reason: string): void {
    if (id != null) {
      (new ResponderImpl(id, this)).error(reason);
    }
    hilog.error(0x0000, JSPackagerClient.TAG, '%{public}s', 'Handling the message failed with reason' + reason);
  }
}
